﻿namespace Resharper.Abstractions.CodeDom.TypeMembers.Constructors
{
  using System.Collections.Generic;
  using System.Linq;
  using JetBrains.Annotations;
  using JetBrains.ReSharper.Psi.CSharp.Tree;
  using Resharper.Abstractions.CodeDom.Statements.Blocks;
  using Resharper.Abstractions.CodeDom.TypeMembers.Functions;
  using Resharper.Abstractions.CodeDom.TypeMembers.Methods;

  /// <summary>Defines the <see cref="Constructor"/> class.</summary>
  public class Constructor : TypeMember, IFunction
  {
    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="Constructor"/> class.</summary>
    /// <param name="method">The method.</param>
    internal Constructor([NotNull] IConstructorDeclaration method) : base(method)
    {
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the body.
    /// </summary>
    public Block Body
    {
      get
      {
        var body = this.InternalConstructor.Body;

        return body != null ? new Block(body) : null;
      }

      set
      {
        if (value == null)
        {
          this.InternalConstructor.SetBody(null);
          return;
        }

        this.InternalConstructor.SetBody(value.InternalBlock);
      }
    }

    /// <summary>
    /// Gets the type.
    /// </summary>
    public Type ReturnType
    {
      get
      {
        var declaredElement = this.InternalConstructor.DeclaredElement;
        if (declaredElement == null)
        {
          return null;
        }

        var returnType = declaredElement.ReturnType;

        return new Type(returnType, this.InternalConstructor.Language);
      }
    }

    /// <summary>
    /// Gets or sets the parameters.
    /// </summary>
    /// <value>The parameters.</value>
    [NotNull]
    public IEnumerable<Parameter> Parameters
    {
      get
      {
        var declarations = this.InternalConstructor.ParameterDeclarations;

        return declarations.Select(p => new Parameter(p));
      }
    }

    /// <summary>
    /// Gets or sets the internal function.
    /// </summary>
    /// <value>The internal function.</value>
    [NotNull]
    internal IConstructorDeclaration InternalConstructor
    {
      get
      {
        return (IConstructorDeclaration)this.InternalTreeNode;
      }
    }

    #endregion
  }
}